package vsqlbuilder.gui;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.LinkedList;

import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableModel;

public class SqlExecuteModel implements TableModel {

	private ResultSet DatabaseRows;
	private ResultSetMetaData DatabaseRowsMetaData;

	public SqlExecuteModel(ResultSet rs) {
		DatabaseRows = rs;

		try {
			DatabaseRowsMetaData = DatabaseRows.getMetaData();
		} catch (SQLException se) {
			System.out
					.println("We got an exception while retrieving metadata for JTable Model constructor:"
							+ "that probably means our SQL is invalid");
			se.printStackTrace();
			System.exit(1);
		}
	}

	// Because is generic shouldn't be parameterized
	private LinkedList<Object> subscribers = new LinkedList<Object>();

	public void addTableModelListener(TableModelListener l) {
		subscribers.add(l);
	}

	public void removeTableModelListener(TableModelListener l) {
		subscribers.remove(l);
	}

	// This function does nothing because we can't edit table right now
	public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
		// TODO [High]: Put JTable in a read/write state not just read only [must modify
		// isCellEditable too]		
		TableModelEvent event = new TableModelEvent(this, rowIndex, rowIndex,
				columnIndex);
		// Send a signal to subscribers to inform about a change in table model
		// with an event
		subscribersSignal(event);
	}

	public Object getValueAt(int rowIndex, int columnIndex) {
		// Get indicate data row
		columnIndex++;
		rowIndex++;
		String value;
		try {
			if (DatabaseRows.absolute(rowIndex)) {
				value = DatabaseRows.getString(columnIndex);
			} else {
				value = "";
			}
			return value;
		} catch (SQLException se) {
			System.out
					.println("We got an exception while executing our query on JTable Model:"
							+ "that probably means our SQL is invalid");
			se.printStackTrace();
			System.exit(1);
		}
		return null;
	}

	// Don't allow to edit cells.
	public boolean isCellEditable(int rowIndex, int columnIndex) {
		return false;
	}

	// Get Name of every column
	public String getColumnName(int columnIndex) {
		columnIndex++;
		try {
			String value = DatabaseRowsMetaData.getColumnName(columnIndex);
			return value;
		} catch (SQLException se) {
			System.out
					.println("We got an exception while retrieving table meta data for JTable Model:"
							+ "that probably means our SQL is invalid");
			se.printStackTrace();
			System.exit(1);
		}
		return null;
	}

	// return class on every column in this case all are strings
	public Class<String> getColumnClass(int columnIndex) {
		return String.class;
	}

	public int getRowCount() {
		int count = 0;
		try {
			DatabaseRows.last();
			count = DatabaseRows.getRow();
			DatabaseRows.beforeFirst();
		} catch (SQLException se) {
			count = 0;
			System.out
					.println("We got an exception while retrieving count rows retrived by query:"
							+ "that probably means our SQL is invalid");
			se.printStackTrace();
			System.exit(1);
		}

		return count;
	}

	public int getColumnCount() {
		int value = 0;
		try {
			value = DatabaseRowsMetaData.getColumnCount();
		} catch (SQLException se) {
			System.out
					.println("We got an exception while retrieving metadata column count for JTable Model constructor:"
							+ "that probably means our SQL is invalid");
			se.printStackTrace();
			System.exit(1);
		}
		return value;
	}

	private void subscribersSignal(TableModelEvent event) {
		int i;
		// Inform change to all subscribers registered
		for (i = 0; i < subscribers.size(); i++)
			((TableModelListener) subscribers.get(i)).tableChanged(event);
	}

}
